import type { LoginParams, RoleInfo, UserInfo } from '@/api/sys/model/userModel';
import { getUserInfo, loginApi } from '@/api/sys/user';
import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY } from '@/enums/cacheEnum';
import { PageEnum } from '@/enums/pageEnum';
import { router } from '@/router';
import projectSetting from '@/settings/projectSetting';
import { getAuthCache, setAuthCache } from '@/utils/auth';
import type { ErrorMessageMode } from '@/utils/axios/types';
import { Persistent } from '@/utils/cache/persistent';
import { isEmpty } from '@/utils/is';
import { defineStore } from 'pinia';
import { store } from '..';
import { useMultipleTabStore } from './multipleTab';
import { usePermissionStore } from './permission';

type UserState = {
	userInfo: Nullable<UserInfo>;
	token?: string;
	roleInfo: RoleInfo[];
	homePath: string;
	lastUpdateTime: number;
	sessionTimeout?: boolean;
};

export const useUserStore = defineStore({
	id: 'app-user',
	state: (): UserState => ({
		userInfo: null,
		token: undefined,
		roleInfo: [],
		homePath: PageEnum.BASE_HOME,
		lastUpdateTime: 0,
		sessionTimeout: false,
	}),
	getters: {
		getUserInfo: state => state.userInfo || getAuthCache<UserInfo>(USER_INFO_KEY) || {},
		getToken(): string {
			return this.token || getAuthCache<string>(TOKEN_KEY);
		},
		getRoleInfo(): RoleInfo[] {
			return isEmpty(this.roleInfo) ? getAuthCache<RoleInfo[]>(ROLES_KEY) : this.roleInfo;
		},
		getHomePath(): string {
			return this.homePath;
		},
		getLastUpdateTime(): number {
			return this.lastUpdateTime;
		},
		getSessionTimeout(): boolean {
			return !!this.sessionTimeout;
		},
	},
	actions: {
		setToken(info: string | undefined) {
			this.token = info || '';
			setAuthCache(TOKEN_KEY, info);
		},
		setUserInfo(info: UserInfo | null) {
			this.userInfo = info;
			this.lastUpdateTime = new Date().getTime();
			setAuthCache(USER_INFO_KEY, info);
		},
		setRoleInfo(info: RoleInfo[]) {
			this.roleInfo = info;
			setAuthCache(ROLES_KEY, info);
		},
		setHomePath(path: string | undefined) {
			this.homePath = path || this.userInfo?.homePath || PageEnum.BASE_HOME;
		},
		setSessionTimeout(flag: boolean) {
			this.sessionTimeout = flag;
		},
		resetState() {
			this.userInfo = null;
			this.token = '';
			this.roleInfo = [];
			this.lastUpdateTime = 0;
			this.sessionTimeout = false;
		},
		async login(
			params: LoginParams & {
				mode?: ErrorMessageMode;
				goHome?: boolean;
			},
		) {
			try {
				const { goHome = true, mode = 'none', ...loginParams } = params;
				const rs = await loginApi(loginParams, mode);
				const token = rs;
				this.setToken(token);
				return this.afterLoginAction(goHome);
			} catch (error) {
				return Promise.reject(error);
			}
		},
		async afterLoginAction(goHome?: boolean) {
			if (!this.getToken) return null;
			const userInfo = await this.getUserInfoAction();
			const permissionStore = usePermissionStore();
			if (!permissionStore.isDynamicAddedRoute) {
				const routes = await permissionStore.buildRoutesAction();
				permissionStore.generateRoutes(routes);
			}
			goHome && router.replace(this.getHomePath);
			return userInfo;
		},
		async getUserInfoAction() {
			if (!this.getToken) return null;
			const userInfo = await getUserInfo();
			const { roleList, userId, name, homePath } = userInfo;
			this.setRoleInfo(roleList);
			this.setUserInfo({ userId, name });
			homePath && this.setHomePath(homePath);
			return userInfo;
		},
		async logout(goLogin = false) {
			if (this.getToken) {
				try {
					// TODO: 后台登出接口
					// await doLogout();
				} catch {
					console.log('注销Token失败');
				}
			}
			const multipleTabStore = useMultipleTabStore();
			const cacheTab = projectSetting.multiTabsSetting.cache;
			this.setToken(undefined);
			this.setUserInfo(null);
			this.setRoleInfo([]);
			cacheTab && multipleTabStore.resetState();
			Persistent.clearAll(true);
			goLogin && router.push(PageEnum.BASE_LOGIN);
		},
	},
});

// 在setup外部使用
export function useUserStoreOutside() {
	return useUserStore(store);
}
